import 'dart:async';
import 'dart:io';

import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
import 'package:record_mp3/record_mp3.dart';
import 'package:xws/helpers/safe_state.dart';
import 'package:xws/helpers/safe_value_notifier.dart';
import 'package:xws/utils/app_util.dart';
import 'package:xws/utils/log_util.dart';
import 'package:xws/utils/storage_util.dart';
import 'package:xws/utils/theme_util.dart';
import 'package:xws/utils/tools_util.dart';
import 'package:xws/widgets/app_btn.dart';
import 'package:xws/widgets/ex_value_builder.dart';

///  录音状态
enum _RecordStatus { none, recording, pause, playing }

/// 添加录音
class AddRecord extends StatefulWidget {
  const AddRecord({
    Key? key,
    this.max = const Duration(seconds: 10),
    this.initPath,
    this.onPathChanged,
    this.onRecoedIndChange,
    this.initInd,
  }) : super(key: key);

  @override
  _AddRecordState createState() => _AddRecordState();

  final Duration max;

  final String? initPath;

  final Function(String?)? onPathChanged;

  final double? initInd;

  final Function(double? ind)? onRecoedIndChange;
}

class _AddRecordState extends State<AddRecord> with SafeState<AddRecord> {
  late SafeValueNotifier<double> _recordIndicator;
  late SafeValueNotifier<double> _playIndicator;
  late AudioPlayer _audioPlayer;

  _RecordStatus _status = _RecordStatus.none;

  String? _path;

  Timer? _timer;

  StreamSubscription<void>? _complateStream;

  StreamSubscription<Duration>? _playStream;

  @override
  void initState() {
    super.initState();

    _recordIndicator = SafeValueNotifier<double>(0);
    _playIndicator = SafeValueNotifier<double>(0);
    _init();
  }

  @override
  void dispose() {
    _recordIndicator.dispose();
    _playIndicator.dispose();
    _audioPlayer.dispose();
    _cancelTimer();
    _cancelStream();
    _release();
    super.dispose();
  }

  Future<void> _init() async {
    if (widget.initPath != null && widget.initPath!.isNotEmpty) {
      _path = widget.initPath;
      _status = _RecordStatus.pause;
      _recordIndicator.value = widget.initInd ?? 0;
    }

    _audioPlayer = AudioPlayer();
  }

  Future<void> _delFile() async {
    if (_path != null && File(_path!).existsSync()) {
      File(_path!).deleteSync();
    }
  }

  /// 释放
  Future<void> _release() async {
    try {
      if (_status == _RecordStatus.recording) {
        RecordMp3.instance.stop();
      }
    } catch (e) {
      error('_release error $e');
    }
  }

  void _startTimer() {
    _timer = Timer.periodic(const Duration(milliseconds: 100), (Timer t) {
      final int _currMilliseconds = t.tick * 100;
      if (_currMilliseconds < widget.max.inMilliseconds) {
        _recordIndicator.value = t.tick * 100 / widget.max.inMilliseconds;
        widget.onRecoedIndChange?.call(_recordIndicator.value);
      } else {
        _stopRecord();
      }
    });
  }

  void _cancelTimer() {
    _timer?.cancel();
    _timer = null;
  }

  void _cancelStream() {
    _complateStream?.cancel();
    _complateStream = null;
    _playStream?.cancel();
    _playStream = null;
  }

  /// 开始录音
  Future<void> _startRecording() async {
    try {
      final bool p = await getPermission(Permission.microphone);

      if (!p) return;

      _path = (await getLocalPath('records')) + DateTime.now().millisecondsSinceEpoch.toString() + '.mp3';
      _startTimer();
      RecordMp3.instance.start(_path!, (RecordErrorType e) => error(e));
      safeSetState(() => _status = _RecordStatus.recording);
    } catch (e) {
      error('_startRecording error $e');
    }
  }

  /// 结束录音
  Future<void> _stopRecord() async {
    try {
      _cancelTimer();
      RecordMp3.instance.stop();
      safeSetState(() => _status = _RecordStatus.pause);
      widget.onPathChanged?.call(_path);
    } catch (e) {
      error('_stopRecord error $e');
    }
  }

  /// 删除录音
  Future<void> _delRecord() async {
    try {
      safeSetState(() => _status = _RecordStatus.none);
      _recordIndicator.value = 0;
      _playIndicator.value = 0;
      widget.onRecoedIndChange?.call(null);
      await _audioPlayer.release();
      _cancelStream();
      _delFile();
      widget.onPathChanged?.call(null);
    } catch (e) {
      error('_delRecord error $e');
    }
  }

  /// 开始播放
  Future<void> _play() async {
    try {
      await _audioPlayer.play(_path!, isLocal: _path!.startsWith('/'));

      _complateStream ??= _audioPlayer.onPlayerCompletion.listen((_) async {
        await _pause();
        _playIndicator.value = 0;
      });

      _playStream ??= _audioPlayer.onAudioPositionChanged.listen((Duration d) {
        _playIndicator.value = d.inMilliseconds / widget.max.inMilliseconds;
      });

      safeSetState(() => _status = _RecordStatus.playing);
    } catch (e) {
      error('_play error $e');
      et('录音播放出错');
      safeSetState(() => _status = _RecordStatus.none);
    }
  }

  /// 暂停播放
  Future<void> _pause() async {
    try {
      await _audioPlayer.pause();
      safeSetState(() => _status = _RecordStatus.pause);
    } catch (e) {
      error('_pause error $e');
    }
  }

  Future<void> _onTap() async {
    switch (_status) {
      case _RecordStatus.none:
        _startRecording();
        break;
      case _RecordStatus.recording:
        _stopRecord();
        break;
      case _RecordStatus.pause:
        _play();
        break;
      case _RecordStatus.playing:
        _pause();
        break;
      default:
    }
  }

  @override
  Widget build(BuildContext context) {
    return AppBtn(
      onTap: _onTap,
      width: sw - 40,
      height: 50,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[_buildLeading, _buildWave, _buildSufix],
      ),
      padding: const EdgeInsets.symmetric(horizontal: 10),
      color: canvas(context),
      borderRadius: const BorderRadius.vertical(bottom: Radius.circular(4)),
    );
  }

  /// 头部图标
  Widget get _buildLeading {
    if (_status == _RecordStatus.none) return Icon(Icons.mic_rounded, color: theme(context));

    if (_status == _RecordStatus.recording) return Icon(Icons.stop_rounded, color: red(context));

    if (_status == _RecordStatus.pause) return Icon(Icons.play_arrow_rounded, color: theme(context));

    if (_status == _RecordStatus.playing) return Icon(Icons.pause_rounded, color: theme(context));

    return Icon(Icons.add_rounded, color: theme(context));
  }

  /// 尾部图标
  Widget get _buildSufix {
    if (_status == _RecordStatus.none || _status == _RecordStatus.recording) return const Icon(Icons.delete_rounded, color: Colors.transparent);

    return GestureDetector(
      onTap: _delRecord,
      child: Icon(Icons.delete_rounded, color: red(context)),
    );
  }

  /// 构建波形图
  Widget get _buildWave {
    return Expanded(
      child: Stack(
        alignment: Alignment.center,
        children: <Widget>[
          ExValueBuilder<double>(
            child: _buildWaveBox(),
            valueListenable: _recordIndicator,
            builder: (_, double v, Widget? child) {
              if (v == 0)
                return Positioned(
                  left: 10,
                  child: Text(
                    '点击开始录音',
                    style: TextStyle(
                      color: disable(context),
                    ),
                  ),
                );
              return ClipPath(
                clipper: _IndicatorClipper(v),
                child: child,
              );
            },
          ),
          ExValueBuilder<double>(
            child: _buildWaveBox(color: theme(context)),
            valueListenable: _playIndicator,
            builder: (_, double v, Widget? child) {
              return ClipPath(
                clipper: _IndicatorClipper(v),
                child: child,
              );
            },
          ),
        ],
      ),
    );
  }

  /// 构建一层着色波浪
  Widget _buildWaveBox({Color? color}) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: _recordWave
          .map(
            (double w) => Container(
              width: 3,
              height: w,
              margin: const EdgeInsets.only(right: 3),
              decoration: BoxDecoration(
                color: color ?? disable(context).withOpacity(0.2),
                borderRadius: BorderRadius.circular(2),
              ),
            ),
          )
          .toList(),
    );
  }
}

/// 波形图数据
const List<double> _recordWave = <double>[
  2,
  2,
  4,
  4,
  7,
  7,
  7,
  10,
  10,
  8,
  6,
  4,
  6,
  8,
  10,
  12,
  14,
  12,
  12,
  10,
  8,
  10,
  10,
  12,
  12,
  12,
  14,
  14,
  10,
  10,
  8,
  6,
  4,
  4,
  4,
  2,
];

class _IndicatorClipper extends CustomClipper<Path> {
  _IndicatorClipper(this.value);

  final double value;

  @override
  Path getClip(Size size) {
    return Path()..addRect(Rect.fromLTWH(0, 0, size.width * value, size.height));
  }

  @override
  bool shouldReclip(covariant _IndicatorClipper oldClipper) => oldClipper.value != value;
}
